﻿using System;
using System.Runtime.CompilerServices;

/*
托管的意思，你不用直接操作内存，你需要的时候跟我说。我替你申请，然后给你用，你用完可以告诉我，我帮你释放，如果你忙，忘记告诉我了，我也会在定期去帮你释放的。 
这就是托管，你打交道的不是直接的内存，而是.net clr。
C#的托管资源是由CLR（公共语言运行时）管理的资源，CLR在程序运行时会自动分配和回收托管资源，开发者无需手动管理。包括但不限于以下几种：
1. 对象：C#中的所有对象都是托管资源，包括类对象、数组、委托、接口等。
2. 内存：C#中的内存管理是由CLR自动进行的，CLR会自动为对象分配内存，并在对象不再使用时自动回收内存。
3. 线程：C#中的线程是托管线程，由CLR进行管理。
4. 异常处理：C#中的异常处理机制也是由CLR进行管理的，CLR会自动捕获并处理异常。
5. IO操作：C#中的IO操作也是由CLR进行管理的，CLR提供了一系列的类和接口来实现文件读写（FileStream 类就是一个托管类，它继承自 Stream 类，提供了对磁盘文件的读写操作）、网络通信等IO操作。
6. 反射：C#中的反射机制也是托管资源，通过反射可以动态地获取和操作程序集、类型、成员等。
7. 事件：C#中的事件机制也是托管资源，事件的订阅和触发都是由CLR进行管理的。
 
非托管的意思就是你要自己负责管理内存，这里所说的内存管理。实际上只是堆上的内存管理，栈内存和以前的一样，函数退出则释放
非托管资源是由操作系统管理的资源，这些资源需要手动分配和释放，否则会导致内存泄漏和资源泄漏等问题。包括但不限于以下几种：
1. COM组件：COM组件是一种非托管代码，它们是以二进制格式编写的动态链接库（DLL）。在C#中，可以使用Interop服务来访问COM组件。
2. Win32 API：Win32 API是一组用于访问Windows操作系统的函数和数据结构。这些函数和数据结构是以非托管的C/C++语言编写的，可以使用DllImport属性在C#中访问它们。
3. 非托管DLL：非托管DLL是由C/C++编写的动态链接库，其中包含了与操作系统相关的功能。可以使用DllImport属性在C#中访问非托管DLL。
4. 文件系统：文件系统是一种非托管资源，它包含了文件和文件夹，可以使用System.IO命名空间中的类来访问它们。一些非托管的 API，比如 Win32 API 中的 CreateFile、ReadFile、WriteFile 等函数。
5. 数据库：数据库是一种非托管资源，它包含了数据和结构，可以使用ADO.NET或其他ORM框架来访问它们。
6. 网络：网络是一种非托管资源，它包含了网络协议和设备，可以使用System.Net命名空间中的类来访问它们。
7. 图形界面：图形界面是一种非托管资源，它包含了窗口、控件和图形渲染，可以使用Windows Forms、WPF或其他UI框架来访问它们。
 */

namespace Sunny.FrameDecoder
{
    /// <summary>
    /// 释放对象接口
    /// </summary>
    public interface IDisposableObject : IDisposable
    {
        /// <summary>
        /// 是否释放标志
        /// </summary>
        bool IsDisposed { get; }

        /// <summary>
        /// 判断是否已经被释放，如果是，则抛出异常。
        /// </summary>
        void ThrowIfDisposed();
    }

    /// <summary>
    /// 释放对象基类
    /// 继承的子类可以实现析构函数，因为析构函数不能重载
    /// </summary>
    public abstract class DisposableObject : IDisposableObject
    {
        /// <summary>
        /// 是否释放标志
        /// </summary>
        private volatile bool _disposed;

        /// <summary>
        /// 保证重复释放资源时，不重复释放
        /// </summary>
        public bool IsDisposed => _disposed;

        /// <summary>
        /// 判断是否已经被释放，如果是，则抛出异常。
        /// </summary>
        /// <exception cref="ObjectDisposedException"></exception>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ThrowIfDisposed()
        {
            if (IsDisposed) throw new ObjectDisposedException(this.GetType().FullName);
        }

        /// <summary>
        /// 释放对象
        /// </summary>
        /// <param name="disposing">ture时一般位主动调用释放，false一般为GC调用析构函数时释放</param>
        protected virtual void Dispose(bool disposing)
        {
            //if (IsDisposed) return;

            //if (disposing)
            //{
            //    //释放托管资源：由CLR管理分配和释放的资源，即由CLR里new出来的对象；
            //}

            // 释放非托管资源：不受CLR管理的对象
            // 例如：文件流、图像图形类、数据库的连接，网络连接，系统的窗口句柄，打印机资源等，这类资源一般不存在堆上。可以认为操作系统资源的一组API。

            // 让类知道自己已经被释放
            _disposed = true;
        }

        /// <summary>
        /// 实现IDisposable中的Dispose方法
        /// 外部手动调用或者在using中自动调用，同时释放托管资源和非托管资源
        /// </summary>
        public virtual void Dispose()
        {
            // 必须为true
            Dispose(true);

            // 通知GC垃圾回收机制不再调用终结器（析构器）
            GC.SuppressFinalize(this);
        }

        /*
        ///<summary>
        /// 不是必要的，提供一个Close方法仅仅是为了更符合其他语言（如C++）的规范
        ///</summary>
        public void Close()
        {
            Dispose();
        }
        
        /// <summary>
        /// 必须，以备程序员忘记了显式调用Dispose方法
        /// 析构函数，编译器自动生成Finalize()函数由GC自动调用，保证资源被回收。
        /// 最好不要声明空析构函数，如果没有引用非托管资源就不需要显示声明析构函数，会造成性能问题，系统会自动生成默认析构函数
        /// </summary>
        ~DisposableObject()
        {
            // 此处只需要释放非托管代码即可，因为GC调用时该对象资源可能还不需要释放
            // 必须为false
            Dispose(false);
        }
        */
    }
}
